webscout 8.2.2__py3-none-any.whl → 8.2.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/AIauto.py +112 -22
- webscout/AIbase.py +144 -7
- webscout/AIutel.py +249 -131
- webscout/Bard.py +579 -206
- webscout/DWEBS.py +78 -35
- webscout/__init__.py +0 -1
- webscout/cli.py +256 -0
- webscout/conversation.py +307 -436
- webscout/exceptions.py +23 -0
- webscout/prompt_manager.py +56 -42
- webscout/version.py +1 -1
- webscout/webscout_search.py +65 -47
- webscout/webscout_search_async.py +81 -126
- webscout/yep_search.py +93 -43
- {webscout-8.2.2.dist-info → webscout-8.2.7.dist-info}/METADATA +172 -52
- webscout-8.2.7.dist-info/RECORD +26 -0
- {webscout-8.2.2.dist-info → webscout-8.2.7.dist-info}/WHEEL +1 -1
- webscout-8.2.7.dist-info/entry_points.txt +3 -0
- webscout-8.2.7.dist-info/top_level.txt +1 -0
- inferno/__init__.py +0 -6
- inferno/__main__.py +0 -9
- inferno/cli.py +0 -6
- webscout/Extra/GitToolkit/__init__.py +0 -10
- webscout/Extra/GitToolkit/gitapi/__init__.py +0 -12
- webscout/Extra/GitToolkit/gitapi/repository.py +0 -195
- webscout/Extra/GitToolkit/gitapi/user.py +0 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +0 -62
- webscout/Extra/YTToolkit/YTdownloader.py +0 -957
- webscout/Extra/YTToolkit/__init__.py +0 -3
- webscout/Extra/YTToolkit/transcriber.py +0 -476
- webscout/Extra/YTToolkit/ytapi/__init__.py +0 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +0 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +0 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +0 -45
- webscout/Extra/YTToolkit/ytapi/https.py +0 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +0 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +0 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +0 -8
- webscout/Extra/YTToolkit/ytapi/query.py +0 -40
- webscout/Extra/YTToolkit/ytapi/stream.py +0 -63
- webscout/Extra/YTToolkit/ytapi/utils.py +0 -62
- webscout/Extra/YTToolkit/ytapi/video.py +0 -232
- webscout/Extra/__init__.py +0 -7
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -849
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/Extra/gguf.py +0 -682
- webscout/Extra/tempmail/__init__.py +0 -28
- webscout/Extra/tempmail/async_utils.py +0 -141
- webscout/Extra/tempmail/base.py +0 -161
- webscout/Extra/tempmail/cli.py +0 -187
- webscout/Extra/tempmail/emailnator.py +0 -84
- webscout/Extra/tempmail/mail_tm.py +0 -361
- webscout/Extra/tempmail/temp_mail_io.py +0 -292
- webscout/Extra/weather.py +0 -194
- webscout/Extra/weather_ascii.py +0 -76
- webscout/LLM.py +0 -442
- webscout/Litlogger/__init__.py +0 -67
- webscout/Litlogger/core/__init__.py +0 -6
- webscout/Litlogger/core/level.py +0 -23
- webscout/Litlogger/core/logger.py +0 -165
- webscout/Litlogger/handlers/__init__.py +0 -12
- webscout/Litlogger/handlers/console.py +0 -33
- webscout/Litlogger/handlers/file.py +0 -143
- webscout/Litlogger/handlers/network.py +0 -173
- webscout/Litlogger/styles/__init__.py +0 -7
- webscout/Litlogger/styles/colors.py +0 -249
- webscout/Litlogger/styles/formats.py +0 -458
- webscout/Litlogger/styles/text.py +0 -87
- webscout/Litlogger/utils/__init__.py +0 -6
- webscout/Litlogger/utils/detectors.py +0 -153
- webscout/Litlogger/utils/formatters.py +0 -200
- webscout/Local/__init__.py +0 -12
- webscout/Local/__main__.py +0 -9
- webscout/Local/api.py +0 -576
- webscout/Local/cli.py +0 -516
- webscout/Local/config.py +0 -75
- webscout/Local/llm.py +0 -287
- webscout/Local/model_manager.py +0 -253
- webscout/Local/server.py +0 -721
- webscout/Local/utils.py +0 -93
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -250
- webscout/Provider/AISEARCH/ISou.py +0 -256
- webscout/Provider/AISEARCH/Perplexity.py +0 -359
- webscout/Provider/AISEARCH/__init__.py +0 -10
- webscout/Provider/AISEARCH/felo_search.py +0 -228
- webscout/Provider/AISEARCH/genspark_search.py +0 -208
- webscout/Provider/AISEARCH/hika_search.py +0 -194
- webscout/Provider/AISEARCH/iask_search.py +0 -436
- webscout/Provider/AISEARCH/monica_search.py +0 -246
- webscout/Provider/AISEARCH/scira_search.py +0 -324
- webscout/Provider/AISEARCH/webpilotai_search.py +0 -281
- webscout/Provider/Aitopia.py +0 -292
- webscout/Provider/AllenAI.py +0 -413
- webscout/Provider/Andi.py +0 -228
- webscout/Provider/Blackboxai.py +0 -229
- webscout/Provider/C4ai.py +0 -432
- webscout/Provider/ChatGPTClone.py +0 -226
- webscout/Provider/ChatGPTES.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Chatify.py +0 -175
- webscout/Provider/Cloudflare.py +0 -273
- webscout/Provider/Cohere.py +0 -208
- webscout/Provider/DeepSeek.py +0 -196
- webscout/Provider/Deepinfra.py +0 -297
- webscout/Provider/ElectronHub.py +0 -709
- webscout/Provider/ExaAI.py +0 -261
- webscout/Provider/ExaChat.py +0 -342
- webscout/Provider/Free2GPT.py +0 -241
- webscout/Provider/GPTWeb.py +0 -193
- webscout/Provider/Gemini.py +0 -169
- webscout/Provider/GithubChat.py +0 -367
- webscout/Provider/Glider.py +0 -211
- webscout/Provider/Groq.py +0 -670
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HeckAI.py +0 -233
- webscout/Provider/HuggingFaceChat.py +0 -462
- webscout/Provider/Hunyuan.py +0 -272
- webscout/Provider/Jadve.py +0 -266
- webscout/Provider/Koboldai.py +0 -381
- webscout/Provider/LambdaChat.py +0 -392
- webscout/Provider/Llama.py +0 -200
- webscout/Provider/Llama3.py +0 -204
- webscout/Provider/Marcus.py +0 -148
- webscout/Provider/Netwrck.py +0 -228
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/__init__.py +0 -25
- webscout/Provider/OPENAI/base.py +0 -46
- webscout/Provider/OPENAI/c4ai.py +0 -367
- webscout/Provider/OPENAI/chatgpt.py +0 -549
- webscout/Provider/OPENAI/chatgptclone.py +0 -460
- webscout/Provider/OPENAI/deepinfra.py +0 -272
- webscout/Provider/OPENAI/e2b.py +0 -1350
- webscout/Provider/OPENAI/exaai.py +0 -404
- webscout/Provider/OPENAI/exachat.py +0 -433
- webscout/Provider/OPENAI/freeaichat.py +0 -352
- webscout/Provider/OPENAI/glider.py +0 -316
- webscout/Provider/OPENAI/heckai.py +0 -337
- webscout/Provider/OPENAI/llmchatco.py +0 -327
- webscout/Provider/OPENAI/netwrck.py +0 -348
- webscout/Provider/OPENAI/opkfc.py +0 -488
- webscout/Provider/OPENAI/scirachat.py +0 -463
- webscout/Provider/OPENAI/sonus.py +0 -294
- webscout/Provider/OPENAI/standardinput.py +0 -425
- webscout/Provider/OPENAI/textpollinations.py +0 -285
- webscout/Provider/OPENAI/toolbaz.py +0 -405
- webscout/Provider/OPENAI/typegpt.py +0 -346
- webscout/Provider/OPENAI/uncovrAI.py +0 -455
- webscout/Provider/OPENAI/utils.py +0 -211
- webscout/Provider/OPENAI/venice.py +0 -413
- webscout/Provider/OPENAI/wisecat.py +0 -381
- webscout/Provider/OPENAI/writecream.py +0 -156
- webscout/Provider/OPENAI/x0gpt.py +0 -371
- webscout/Provider/OPENAI/yep.py +0 -327
- webscout/Provider/OpenGPT.py +0 -199
- webscout/Provider/Openai.py +0 -496
- webscout/Provider/PI.py +0 -344
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Phind.py +0 -535
- webscout/Provider/PizzaGPT.py +0 -198
- webscout/Provider/QwenLM.py +0 -254
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -278
- webscout/Provider/TTI/AiForce/__init__.py +0 -22
- webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
- webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
- webscout/Provider/TTI/ImgSys/__init__.py +0 -23
- webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
- webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
- webscout/Provider/TTI/Nexra/__init__.py +0 -22
- webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
- webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
- webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
- webscout/Provider/TTI/__init__.py +0 -12
- webscout/Provider/TTI/aiarta/__init__.py +0 -2
- webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
- webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
- webscout/Provider/TTI/artbit/__init__.py +0 -22
- webscout/Provider/TTI/artbit/async_artbit.py +0 -155
- webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
- webscout/Provider/TTI/fastflux/__init__.py +0 -22
- webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
- webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
- webscout/Provider/TTI/huggingface/__init__.py +0 -22
- webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
- webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
- webscout/Provider/TTI/piclumen/__init__.py +0 -23
- webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
- webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
- webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
- webscout/Provider/TTI/talkai/__init__.py +0 -4
- webscout/Provider/TTI/talkai/async_talkai.py +0 -229
- webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
- webscout/Provider/TTS/__init__.py +0 -7
- webscout/Provider/TTS/deepgram.py +0 -156
- webscout/Provider/TTS/elevenlabs.py +0 -111
- webscout/Provider/TTS/gesserit.py +0 -127
- webscout/Provider/TTS/murfai.py +0 -113
- webscout/Provider/TTS/parler.py +0 -111
- webscout/Provider/TTS/speechma.py +0 -180
- webscout/Provider/TTS/streamElements.py +0 -333
- webscout/Provider/TTS/utils.py +0 -280
- webscout/Provider/TeachAnything.py +0 -187
- webscout/Provider/TextPollinationsAI.py +0 -231
- webscout/Provider/TwoAI.py +0 -199
- webscout/Provider/Venice.py +0 -219
- webscout/Provider/VercelAI.py +0 -234
- webscout/Provider/WebSim.py +0 -228
- webscout/Provider/WiseCat.py +0 -196
- webscout/Provider/Writecream.py +0 -211
- webscout/Provider/WritingMate.py +0 -197
- webscout/Provider/Youchat.py +0 -330
- webscout/Provider/__init__.py +0 -198
- webscout/Provider/ai4chat.py +0 -202
- webscout/Provider/aimathgpt.py +0 -189
- webscout/Provider/akashgpt.py +0 -342
- webscout/Provider/askmyai.py +0 -158
- webscout/Provider/asksteve.py +0 -203
- webscout/Provider/bagoodex.py +0 -145
- webscout/Provider/cerebras.py +0 -242
- webscout/Provider/chatglm.py +0 -205
- webscout/Provider/cleeai.py +0 -213
- webscout/Provider/copilot.py +0 -428
- webscout/Provider/elmo.py +0 -234
- webscout/Provider/freeaichat.py +0 -271
- webscout/Provider/gaurish.py +0 -244
- webscout/Provider/geminiapi.py +0 -208
- webscout/Provider/geminiprorealtime.py +0 -160
- webscout/Provider/granite.py +0 -187
- webscout/Provider/hermes.py +0 -219
- webscout/Provider/julius.py +0 -223
- webscout/Provider/koala.py +0 -268
- webscout/Provider/labyrinth.py +0 -340
- webscout/Provider/learnfastai.py +0 -266
- webscout/Provider/lepton.py +0 -194
- webscout/Provider/llama3mitril.py +0 -180
- webscout/Provider/llamatutor.py +0 -192
- webscout/Provider/llmchat.py +0 -213
- webscout/Provider/llmchatco.py +0 -311
- webscout/Provider/meta.py +0 -794
- webscout/Provider/multichat.py +0 -325
- webscout/Provider/promptrefine.py +0 -193
- webscout/Provider/scira_chat.py +0 -277
- webscout/Provider/scnet.py +0 -187
- webscout/Provider/searchchat.py +0 -293
- webscout/Provider/sonus.py +0 -208
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/toolbaz.py +0 -320
- webscout/Provider/turboseek.py +0 -219
- webscout/Provider/tutorai.py +0 -252
- webscout/Provider/typefully.py +0 -280
- webscout/Provider/typegpt.py +0 -232
- webscout/Provider/uncovr.py +0 -312
- webscout/Provider/x0gpt.py +0 -256
- webscout/Provider/yep.py +0 -376
- webscout/litagent/__init__.py +0 -29
- webscout/litagent/agent.py +0 -455
- webscout/litagent/constants.py +0 -60
- webscout/litprinter/__init__.py +0 -59
- webscout/scout/__init__.py +0 -8
- webscout/scout/core/__init__.py +0 -7
- webscout/scout/core/crawler.py +0 -140
- webscout/scout/core/scout.py +0 -568
- webscout/scout/core/search_result.py +0 -96
- webscout/scout/core/text_analyzer.py +0 -63
- webscout/scout/core/text_utils.py +0 -277
- webscout/scout/core/web_analyzer.py +0 -52
- webscout/scout/core.py +0 -881
- webscout/scout/element.py +0 -460
- webscout/scout/parsers/__init__.py +0 -69
- webscout/scout/parsers/html5lib_parser.py +0 -172
- webscout/scout/parsers/html_parser.py +0 -236
- webscout/scout/parsers/lxml_parser.py +0 -178
- webscout/scout/utils.py +0 -37
- webscout/swiftcli/__init__.py +0 -809
- webscout/zeroart/__init__.py +0 -55
- webscout/zeroart/base.py +0 -60
- webscout/zeroart/effects.py +0 -99
- webscout/zeroart/fonts.py +0 -816
- webscout-8.2.2.dist-info/RECORD +0 -309
- webscout-8.2.2.dist-info/entry_points.txt +0 -5
- webscout-8.2.2.dist-info/top_level.txt +0 -3
- webstoken/__init__.py +0 -30
- webstoken/classifier.py +0 -189
- webstoken/keywords.py +0 -216
- webstoken/language.py +0 -128
- webstoken/ner.py +0 -164
- webstoken/normalizer.py +0 -35
- webstoken/processor.py +0 -77
- webstoken/sentiment.py +0 -206
- webstoken/stemmer.py +0 -73
- webstoken/tagger.py +0 -60
- webstoken/tokenizer.py +0 -158
- {webscout-8.2.2.dist-info → webscout-8.2.7.dist-info/licenses}/LICENSE.md +0 -0
webscout/AIauto.py
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides the AUTO provider, which automatically selects and uses
|
|
3
|
+
an available LLM provider from the webscout library that doesn't require
|
|
4
|
+
API keys or cookies.
|
|
5
|
+
"""
|
|
6
|
+
|
|
1
7
|
from webscout.AIbase import Provider
|
|
2
8
|
from webscout.exceptions import AllProvidersFailure
|
|
3
9
|
from typing import Union, Any, Dict, Generator
|
|
@@ -7,8 +13,20 @@ import random
|
|
|
7
13
|
import inspect
|
|
8
14
|
|
|
9
15
|
def load_providers():
|
|
16
|
+
"""
|
|
17
|
+
Dynamically loads all Provider classes from the webscout.Provider package.
|
|
18
|
+
|
|
19
|
+
Identifies providers that require special authentication parameters like
|
|
20
|
+
'api_key', 'cookie_file', or 'cookie_path'.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
tuple: A tuple containing:
|
|
24
|
+
- provider_map (dict): A dictionary mapping uppercase provider names to their classes.
|
|
25
|
+
- api_key_providers (set): A set of uppercase provider names requiring special authentication.
|
|
26
|
+
"""
|
|
10
27
|
provider_map = {}
|
|
11
28
|
api_key_providers = set()
|
|
29
|
+
cookie_providers = set()
|
|
12
30
|
provider_package = importlib.import_module("webscout.Provider")
|
|
13
31
|
|
|
14
32
|
for _, module_name, _ in pkgutil.iter_modules(provider_package.__path__):
|
|
@@ -18,16 +36,24 @@ def load_providers():
|
|
|
18
36
|
attr = getattr(module, attr_name)
|
|
19
37
|
if isinstance(attr, type) and issubclass(attr, Provider) and attr != Provider:
|
|
20
38
|
provider_map[attr_name.upper()] = attr
|
|
21
|
-
# Check if the provider needs
|
|
22
|
-
|
|
39
|
+
# Check if the provider needs special parameters
|
|
40
|
+
sig = inspect.signature(attr.__init__).parameters
|
|
41
|
+
if 'api_key' in sig:
|
|
23
42
|
api_key_providers.add(attr_name.upper())
|
|
43
|
+
if 'cookie_file' in sig or 'cookie_path' in sig:
|
|
44
|
+
cookie_providers.add(attr_name.upper())
|
|
24
45
|
except Exception:
|
|
25
46
|
pass
|
|
26
|
-
return provider_map, api_key_providers
|
|
47
|
+
return provider_map, api_key_providers.union(cookie_providers)
|
|
27
48
|
|
|
28
49
|
provider_map, api_key_providers = load_providers()
|
|
29
50
|
|
|
30
51
|
class AUTO(Provider):
|
|
52
|
+
"""
|
|
53
|
+
An automatic provider that cycles through available free providers
|
|
54
|
+
until one successfully processes the request. Excludes providers
|
|
55
|
+
requiring API keys or cookies by default.
|
|
56
|
+
"""
|
|
31
57
|
def __init__(
|
|
32
58
|
self,
|
|
33
59
|
is_conversation: bool = True,
|
|
@@ -40,26 +66,51 @@ class AUTO(Provider):
|
|
|
40
66
|
history_offset: int = 10250,
|
|
41
67
|
act: str = None,
|
|
42
68
|
exclude: list[str] = [],
|
|
69
|
+
print_provider_info: bool = False,
|
|
43
70
|
):
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
71
|
+
"""
|
|
72
|
+
Initializes the AUTO provider.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
is_conversation (bool): Flag for conversational mode. Defaults to True.
|
|
76
|
+
max_tokens (int): Maximum tokens for the response. Defaults to 600.
|
|
77
|
+
timeout (int): Request timeout in seconds. Defaults to 30.
|
|
78
|
+
intro (str, optional): Introductory prompt. Defaults to None.
|
|
79
|
+
filepath (str, optional): Path for conversation history. Defaults to None.
|
|
80
|
+
update_file (bool): Whether to update the history file. Defaults to True.
|
|
81
|
+
proxies (dict): Proxies for requests. Defaults to {}.
|
|
82
|
+
history_offset (int): History character offset limit. Defaults to 10250.
|
|
83
|
+
act (str, optional): Awesome prompt key. Defaults to None.
|
|
84
|
+
exclude (list[str]): List of provider names (uppercase) to exclude. Defaults to [].
|
|
85
|
+
print_provider_info (bool): Whether to print the name of the successful provider. Defaults to False.
|
|
86
|
+
"""
|
|
87
|
+
self.provider = None # type: Provider
|
|
88
|
+
self.provider_name = None # type: str
|
|
89
|
+
self.is_conversation: bool = is_conversation
|
|
90
|
+
self.max_tokens: int = max_tokens
|
|
91
|
+
self.timeout: int = timeout
|
|
92
|
+
self.intro: str = intro
|
|
93
|
+
self.filepath: str = filepath
|
|
94
|
+
self.update_file: bool = update_file
|
|
95
|
+
self.proxies: dict = proxies
|
|
96
|
+
self.history_offset: int = history_offset
|
|
97
|
+
self.act: str = act
|
|
98
|
+
self.exclude: list[str] = [e.upper() for e in exclude]
|
|
99
|
+
self.print_provider_info: bool = print_provider_info
|
|
100
|
+
|
|
56
101
|
|
|
57
102
|
@property
|
|
58
103
|
def last_response(self) -> dict[str, Any]:
|
|
104
|
+
"""
|
|
105
|
+
Returns the last response dictionary from the successful provider.
|
|
106
|
+
"""
|
|
59
107
|
return self.provider.last_response if self.provider else {}
|
|
60
108
|
|
|
61
109
|
@property
|
|
62
110
|
def conversation(self) -> object:
|
|
111
|
+
"""
|
|
112
|
+
Returns the conversation object from the successful provider.
|
|
113
|
+
"""
|
|
63
114
|
return self.provider.conversation if self.provider else None
|
|
64
115
|
|
|
65
116
|
def ask(
|
|
@@ -69,8 +120,21 @@ class AUTO(Provider):
|
|
|
69
120
|
raw: bool = False,
|
|
70
121
|
optimizer: str = None,
|
|
71
122
|
conversationally: bool = False,
|
|
72
|
-
run_new_test: bool = False,
|
|
73
123
|
) -> Union[Dict, Generator]:
|
|
124
|
+
"""
|
|
125
|
+
Sends the prompt to providers, trying each available free provider
|
|
126
|
+
in a random order until one succeeds.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
prompt (str): The user's prompt.
|
|
130
|
+
stream (bool): Whether to stream the response. Defaults to False.
|
|
131
|
+
raw (bool): Whether to return the raw response format. Defaults to False.
|
|
132
|
+
optimizer (str, optional): Name of the optimizer to use. Defaults to None.
|
|
133
|
+
conversationally (bool): Whether to apply optimizer conversationally. Defaults to False.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Union[Dict, Generator]: The response dictionary or generator from the successful provider.
|
|
137
|
+
"""
|
|
74
138
|
ask_kwargs = {
|
|
75
139
|
"prompt": prompt,
|
|
76
140
|
"stream": stream,
|
|
@@ -105,6 +169,9 @@ class AUTO(Provider):
|
|
|
105
169
|
act=self.act,
|
|
106
170
|
)
|
|
107
171
|
response = self.provider.ask(**ask_kwargs)
|
|
172
|
+
# Print provider info if enabled
|
|
173
|
+
if self.print_provider_info:
|
|
174
|
+
print(f"\033[1;34m{self.provider_name}\033[0m\n")
|
|
108
175
|
return response
|
|
109
176
|
except Exception:
|
|
110
177
|
continue
|
|
@@ -118,26 +185,49 @@ class AUTO(Provider):
|
|
|
118
185
|
stream: bool = False,
|
|
119
186
|
optimizer: str = None,
|
|
120
187
|
conversationally: bool = False,
|
|
121
|
-
run_new_test: bool = False,
|
|
122
188
|
) -> Union[str, Generator[str, None, None]]:
|
|
189
|
+
"""
|
|
190
|
+
Provides a simplified chat interface, returning the message string(s).
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
prompt (str): The user's prompt.
|
|
194
|
+
stream (bool): Whether to stream the response. Defaults to False.
|
|
195
|
+
optimizer (str, optional): Name of the optimizer to use. Defaults to None.
|
|
196
|
+
conversationally (bool): Whether to apply optimizer conversationally. Defaults to False.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Union[str, Generator[str, None, None]]: The response string or a generator yielding
|
|
200
|
+
response chunks.
|
|
201
|
+
"""
|
|
202
|
+
# run_new_test is not used in the current implementation, but we keep it for API compatibility
|
|
123
203
|
response = self.ask(
|
|
124
204
|
prompt,
|
|
125
205
|
stream,
|
|
126
206
|
optimizer=optimizer,
|
|
127
207
|
conversationally=conversationally,
|
|
128
|
-
run_new_test=run_new_test,
|
|
129
208
|
)
|
|
130
209
|
|
|
131
210
|
if stream:
|
|
132
|
-
|
|
211
|
+
for chunk in response:
|
|
212
|
+
yield self.get_message(chunk)
|
|
133
213
|
else:
|
|
134
214
|
return self.get_message(response)
|
|
135
215
|
|
|
136
216
|
def get_message(self, response: dict) -> str:
|
|
217
|
+
"""
|
|
218
|
+
Extracts the message text from the provider's response dictionary.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
response (dict): The response dictionary from the ask method.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
str: The extracted message string.
|
|
225
|
+
"""
|
|
137
226
|
assert self.provider is not None, "Chat with AI first"
|
|
138
227
|
return self.provider.get_message(response)
|
|
139
228
|
|
|
140
229
|
if __name__ == "__main__":
|
|
141
|
-
auto = AUTO()
|
|
142
|
-
response = auto.chat("Hello, how are you?")
|
|
143
|
-
|
|
230
|
+
auto = AUTO(print_provider_info=True)
|
|
231
|
+
response = auto.chat("Hello, how are you?", stream=True)
|
|
232
|
+
for chunk in response:
|
|
233
|
+
print(chunk, end="", flush=True)
|
webscout/AIbase.py
CHANGED
|
@@ -68,15 +68,152 @@ class AsyncProvider(ABC):
|
|
|
68
68
|
class TTSProvider(ABC):
|
|
69
69
|
|
|
70
70
|
@abstractmethod
|
|
71
|
-
def tts(self, text: str) ->
|
|
71
|
+
def tts(self, text: str, voice: str = None, verbose: bool = False) -> str:
|
|
72
|
+
"""Convert text to speech and save to a temporary file.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
text (str): The text to convert to speech
|
|
76
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
77
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
str: Path to the generated audio file
|
|
81
|
+
"""
|
|
72
82
|
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
73
83
|
|
|
84
|
+
def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
|
|
85
|
+
"""Save audio to a specific destination.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
audio_file (str): Path to the source audio file
|
|
89
|
+
destination (str, optional): Destination path. Defaults to current directory with timestamp.
|
|
90
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
str: Path to the saved audio file
|
|
94
|
+
"""
|
|
95
|
+
import shutil
|
|
96
|
+
import os
|
|
97
|
+
from pathlib import Path
|
|
98
|
+
import time
|
|
99
|
+
|
|
100
|
+
source_path = Path(audio_file)
|
|
101
|
+
|
|
102
|
+
if not source_path.exists():
|
|
103
|
+
raise FileNotFoundError(f"Audio file not found: {audio_file}")
|
|
104
|
+
|
|
105
|
+
if destination is None:
|
|
106
|
+
# Create a default destination with timestamp in current directory
|
|
107
|
+
timestamp = int(time.time())
|
|
108
|
+
destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
|
|
109
|
+
|
|
110
|
+
# Ensure the destination directory exists
|
|
111
|
+
os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
|
|
112
|
+
|
|
113
|
+
# Copy the file
|
|
114
|
+
shutil.copy2(source_path, destination)
|
|
115
|
+
|
|
116
|
+
if verbose:
|
|
117
|
+
print(f"[debug] Audio saved to {destination}")
|
|
118
|
+
|
|
119
|
+
return destination
|
|
120
|
+
|
|
121
|
+
def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> Generator[bytes, None, None]:
|
|
122
|
+
"""Stream audio in chunks.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
text (str): The text to convert to speech
|
|
126
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
127
|
+
chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
|
|
128
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
129
|
+
|
|
130
|
+
Yields:
|
|
131
|
+
Generator[bytes, None, None]: Audio data chunks
|
|
132
|
+
"""
|
|
133
|
+
# Generate the audio file
|
|
134
|
+
audio_file = self.tts(text, voice=voice, verbose=verbose)
|
|
135
|
+
|
|
136
|
+
# Stream the file in chunks
|
|
137
|
+
with open(audio_file, 'rb') as f:
|
|
138
|
+
while chunk := f.read(chunk_size):
|
|
139
|
+
yield chunk
|
|
140
|
+
|
|
74
141
|
class AsyncTTSProvider(ABC):
|
|
75
142
|
|
|
76
143
|
@abstractmethod
|
|
77
|
-
async def tts(self, text: str) ->
|
|
144
|
+
async def tts(self, text: str, voice: str = None, verbose: bool = False) -> str:
|
|
145
|
+
"""Convert text to speech and save to a temporary file asynchronously.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
text (str): The text to convert to speech
|
|
149
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
150
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: Path to the generated audio file
|
|
154
|
+
"""
|
|
78
155
|
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
79
156
|
|
|
157
|
+
async def save_audio(self, audio_file: str, destination: str = None, verbose: bool = False) -> str:
|
|
158
|
+
"""Save audio to a specific destination asynchronously.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
audio_file (str): Path to the source audio file
|
|
162
|
+
destination (str, optional): Destination path. Defaults to current directory with timestamp.
|
|
163
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
str: Path to the saved audio file
|
|
167
|
+
"""
|
|
168
|
+
import shutil
|
|
169
|
+
import os
|
|
170
|
+
from pathlib import Path
|
|
171
|
+
import time
|
|
172
|
+
import asyncio
|
|
173
|
+
|
|
174
|
+
source_path = Path(audio_file)
|
|
175
|
+
|
|
176
|
+
if not source_path.exists():
|
|
177
|
+
raise FileNotFoundError(f"Audio file not found: {audio_file}")
|
|
178
|
+
|
|
179
|
+
if destination is None:
|
|
180
|
+
# Create a default destination with timestamp in current directory
|
|
181
|
+
timestamp = int(time.time())
|
|
182
|
+
destination = os.path.join(os.getcwd(), f"tts_audio_{timestamp}{source_path.suffix}")
|
|
183
|
+
|
|
184
|
+
# Ensure the destination directory exists
|
|
185
|
+
os.makedirs(os.path.dirname(os.path.abspath(destination)), exist_ok=True)
|
|
186
|
+
|
|
187
|
+
# Copy the file using asyncio to avoid blocking
|
|
188
|
+
await asyncio.to_thread(shutil.copy2, source_path, destination)
|
|
189
|
+
|
|
190
|
+
if verbose:
|
|
191
|
+
print(f"[debug] Audio saved to {destination}")
|
|
192
|
+
|
|
193
|
+
return destination
|
|
194
|
+
|
|
195
|
+
async def stream_audio(self, text: str, voice: str = None, chunk_size: int = 1024, verbose: bool = False) -> AsyncGenerator[bytes, None]:
|
|
196
|
+
"""Stream audio in chunks asynchronously.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
text (str): The text to convert to speech
|
|
200
|
+
voice (str, optional): The voice to use. Defaults to provider's default voice.
|
|
201
|
+
chunk_size (int, optional): Size of audio chunks to yield. Defaults to 1024.
|
|
202
|
+
verbose (bool, optional): Whether to print debug information. Defaults to False.
|
|
203
|
+
|
|
204
|
+
Yields:
|
|
205
|
+
AsyncGenerator[bytes, None]: Audio data chunks
|
|
206
|
+
"""
|
|
207
|
+
import aiofiles
|
|
208
|
+
|
|
209
|
+
# Generate the audio file
|
|
210
|
+
audio_file = await self.tts(text, voice=voice, verbose=verbose)
|
|
211
|
+
|
|
212
|
+
# Stream the file in chunks
|
|
213
|
+
async with aiofiles.open(audio_file, 'rb') as f:
|
|
214
|
+
while chunk := await f.read(chunk_size):
|
|
215
|
+
yield chunk
|
|
216
|
+
|
|
80
217
|
class ImageProvider(ABC):
|
|
81
218
|
|
|
82
219
|
@abstractmethod
|
|
@@ -85,9 +222,9 @@ class ImageProvider(ABC):
|
|
|
85
222
|
|
|
86
223
|
@abstractmethod
|
|
87
224
|
def save(
|
|
88
|
-
self,
|
|
89
|
-
response: List[bytes],
|
|
90
|
-
name: Optional[str] = None,
|
|
225
|
+
self,
|
|
226
|
+
response: List[bytes],
|
|
227
|
+
name: Optional[str] = None,
|
|
91
228
|
dir: Optional[Union[str, Path]] = None
|
|
92
229
|
) -> List[str]:
|
|
93
230
|
raise NotImplementedError("Method needs to be implemented in subclass")
|
|
@@ -96,8 +233,8 @@ class AsyncImageProvider(ABC):
|
|
|
96
233
|
|
|
97
234
|
@abstractmethod
|
|
98
235
|
async def generate(
|
|
99
|
-
self,
|
|
100
|
-
prompt: str,
|
|
236
|
+
self,
|
|
237
|
+
prompt: str,
|
|
101
238
|
amount: int = 1
|
|
102
239
|
) -> Union[AsyncGenerator[bytes, None], List[bytes]]:
|
|
103
240
|
raise NotImplementedError("Method needs to be implemented in subclass")
|